import Cookies from 'js-cookie'
import config from '../config'
const {
    title
} = config
// 获取url参数
export const getUrlParam = () => {
    let reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
    let result = window.location.search.substr(1).match(reg)
    return result ? decodeURIComponent(result[2]) : null
}

/* 过滤非法字符串 */
export const illegalFilter = (str) => {
    //  let regEn = /[`~!@#$%^&*()_+<>?:"{},.\/'[\]]/im
    let regEn = /[`~!@#$%^&*()_+<>?:"{},./'[\]]/im
    let regCn = /[·！#￥（——）：；“”‘、，|《。》？、【】[\]]/im
    if (regEn.test(str) || regCn.test(str)) return false
    return true
}

/* 判断是否包含calss */
export const hasClass = function (elem, cls) {
    cls = cls || ''
    if (cls.replace(/\s/g, '').length === 0 || !elem) return false
    return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' ')
}

/**
 * @param {*} obj1 对象
 * @param {*} obj2 对象
 * @description 判断两个对象是否相等，这两个对象的值只能是数字或字符串
 */
export const objEqual = (obj1, obj2) => {
    const keysArr1 = Object.keys(obj1)
    const keysArr2 = Object.keys(obj2)
    if (keysArr1.length !== keysArr2.length) return false
    else if (keysArr1.length === 0 && keysArr2.length === 0) return true
    /* eslint-disable-next-line */
    else return !keysArr1.some(key => obj1[key] != obj2[key])
}

export const addClass = function (ele, cls) {
    if (!hasClass(ele, cls)) {
        ele.className = ele.className === '' ? cls : ele.className + ' ' + cls
    }
}
/**
 * @param {Number} times 回调函数需要执行的次数
 * @param {Function} callback 回调函数
 */
export const doCustomTimes = (times, callback) => {
    let i = -1
    while (++i < times) {
        callback(i)
    }
}
/**
 * 判断打开的标签列表里是否已存在这个新添加的路由对象
 */
export const routeHasExist = (tagNavList, routeItem) => {
    let len = tagNavList.length
    let res = false
    doCustomTimes(len, (index) => {
        if (routeEqual(tagNavList[index], routeItem)) res = true
    })
    return res
}
/**
 * @param {*} list 现有标签导航列表
 * @param {*} newRoute 新添加的路由原信息对象
 * @description 如果该newRoute已经存在则不再添加
 */
export const getNewTagList = (list, newRoute) => {
    const {
        name,
        path,
        meta
    } = newRoute
    let newList = [...list]
    if (newList.findIndex(item => item.name === name) >= 0) return newList
    else {
        newList.push({
            name,
            path,
            meta
        })
        return newList
    }
}

/**
 * @param {Array} arr1
 * @param {Array} arr2
 * @description 得到两个数组的并集, 两个数组的元素为数值或字符串
 */
export const getUnion = (arr1, arr2) => {
    return Array.from(new Set([...arr1, ...arr2]))
}
export const removeClass = function (ele, cls) {
    if (hasClass(ele, cls)) {
        let newClass = ' ' + ele.className.replace(/[\t\r\n]/g, '') + ' '
        while (newClass.indexOf(' ' + cls + ' ') >= 0) {
            newClass = newClass.replace(' ' + cls + ' ', ' ')
        }
        ele.className = newClass.replace(/^\s+|\s+$/g, '')
    }
}

export const TOKEN_KEY = 'token'

export const setToken = (token) => {
    Cookies.set(TOKEN_KEY, token, {
        expires: 1
    })
}

export const getToken = () => {
    const token = Cookies.get(TOKEN_KEY)
    if (token) return token
    else return false
}
export function removeToken () {
    return Cookies.remove(TOKEN_KEY)
}
export const getRouteTitleHandled = (route) => {
    let router = {
        ...route
    }
    let meta = {
        ...route.meta
    }
    let title = ''
    if (meta.title) {
        if (typeof meta.title === 'function') {
            meta.__titleIsFunction__ = true
            title = meta.title(router)
        } else title = meta.title
    }
    meta.title = title
    router.meta = meta
    return router
}

export const showTitle = (item, vm) => {
    let {
        title
    } = item.meta
    if (!title) return
    title = (item.meta && item.meta.title) || item.name
    return title
}
/**
 * @description 根据当前跳转的路由设置显示在浏览器标签的title
 * @param {Object} routeItem 路由对象
 * @param {Object} vm Vue实例
 */
export const setTitle = (routeItem, vm) => {
    const handledRoute = getRouteTitleHandled(routeItem)
    const pageTitle = showTitle(handledRoute, vm)
    const resTitle = pageTitle ? `${title} - ${pageTitle}` : title
    window.document.title = resTitle
}

export const hasOneOf = (targetarr, arr) => {
    return targetarr.some(_ => arr.indexOf(_) > -1)
}
/**
 * @param {*} access 用户权限数组，如 ['super_admin', 'admin']
 * @param {*} route 路由列表
 */
export const hasAccess = (access, route) => {
    if (route.meta && route.meta.access) return hasOneOf(access, route.meta.access)
    else return true
}
/**
 * 权鉴
 * @param {*} name 即将跳转的路由name
 * @param {*} access 用户权限数组
 * @param {*} routes 路由列表
 * @description 用户是否可跳转到该页
 */
export const canTurnTo = (name, access, routes) => {
    const routePermissionJudge = (list) => {
        return list.some(item => {
            if (item.children && item.children.length) {
                return routePermissionJudge(item.children)
            } else if (item.name === name) {
                return hasAccess(access, item)
            }
        })
    }
    return routePermissionJudge(routes)
}

/**
 * 判断对象是否有子类
 * @param {*} item 当前对象
 */
export const hasChild = (item) => {
    return item.children && item.children.length
}

/**
 * 根据权限显示侧边栏
 * @param {*} item 当前路由
 * @param {*} access 权限名单
 */
export const showThisMenuEle = (item, roles) => {
    if (item.meta && item.meta.roles && item.meta.roles.length) {
        if (hasOneOf(item.meta.roles, roles)) return true
        else return false
    } else return true
}

/**
 * @param {Array} list 标签列表
 * @param {String} name 当前关闭的标签的name
 */
export const getNextRoute = (list, route) => {
    let res = {}
    if (list.length === 2) {
        res = getHomeRoute(list)
    } else {
        const index = list.findIndex(item => routeEqual(item, route))
        if (index === list.length - 1) res = list[list.length - 2]
        else res = list[index + 1]
    }
    return res
}
/**
 * @description 根据name/params/query判断两个路由对象是否相等
 * @param {*} route1 路由对象
 * @param {*} route2 路由对象
 */
export const routeEqual = (route1, route2) => {
    // const params1 = route1.params || {}
    // const params2 = route2.params || {}
    // const query1 = route1.query || {}
    // const query2 = route2.query || {}
    // return (route1.name === route2.name) && objEqual(params1, params2) && objEqual(query1, query2)
    return route1.name === route2.name
}
/**
 * @param {Array} routers 路由列表数组
 * @description 用于找到路由列表中name为home的对象
 */
export const getHomeRoute = (routers, homeName = 'home') => {
    let i = -1
    let len = routers.length
    let homeRoute = {}
    while (++i < len) {
        let item = routers[i]
        if (item.children && item.children.length) {
            let res = getHomeRoute(item.children, homeName)
            if (res.name) return res
        } else {
            if (item.name === homeName) homeRoute = item
        }
    }
    return homeRoute
}
/**
 * 获取侧边栏
 * @param {*} list 路由列表
 * @param {*} access 权限名单
 */
export const getMenuByRouter = (list, roles) => {
    let res = []
    list.forEach(item => {
        if (!item.meta || (item.meta && !item.meta.hideInMenu)) {
            let obj = {
                icon: (item.meta && item.meta.icon) || '',
                name: item.name,
                meta: item.meta,
                path: item.path,
                component: item.component
            }
            if (hasChild(item) && showThisMenuEle(item, roles)) {
                obj.children = getMenuByRouter(item.children, roles)
            }
            if (showThisMenuEle(item, roles)) res.push(obj)
        }
    })
    // console.log(list, roles, res)
    return res
}

/**
 * @description 本地存储和获取标签导航列表
 */
export const setTagNavListInLocalstorage = list => {
    // localStorage.tagNavList = JSON.stringify(list)
    var curTime = new Date().getTime()
    localStorage.setItem('tagNavData', JSON.stringify({ tagNavList: list, time: curTime }))
}
/**
 * @returns {Array} 其中的每个元素只包含路由原信息中的name, path, meta三项
 */
export const getTagNavListFromLocalstorage = () => {
    let list = localStorage.getItem('tagNavData')
    if (list && (new Date().getTime() > (JSON.parse(list).time + (24 * 60 * 60 * 1000)))) {
        localStorage.removeItem('tagNavData')
        list = localStorage.getItem('tagNavData')
    }
    return list ? JSON.parse(list).tagNavList : []
}
export const formatDate = (date, fmt) => {
    if (/(y+)/.test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
    }
    let o = {
        'M+': date.getMonth() + 1,
        'd+': date.getDate(),
        'h+': date.getHours(),
        'm+': date.getMinutes(),
        's+': date.getSeconds()
    }
    for (let k in o) {
        if (new RegExp(`(${k})`).test(fmt)) {
            let str = o[k] + ''
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str))
        }
    }

    function padLeftZero (str) {
        return ('00' + str).substr(str.length)
    }
    return fmt
}
export const sortData = (array) => {
    var temp = []
    var index = []
    var l = array.length
    for (var i = 0; i < l; i++) {
        for (var j = i + 1; j < l; j++) {
            if (array[i] === array[j]) {
                i++
                j = i
            }
        }
        temp.push(array[i])
        index.push(i)
    }
    return temp
}
/**
 * 保留两位小数
 * @param {*} str 校验单数组字
 * @param {*} len 长度限制
  * @param {*} iszero 为true 不能已0开头
 */
export const clearNoNum = (str, len, iszero) => {
    // 先把非数字的都替换掉，除了数字和.
    str = str.replace(/[^\d.]/g, '')
    // 剔除多于的0
    str = str.replace(/^(0+)/, '0').replace(/^(0[1-9]+)/, str.slice(1))
    // 保证只有出现一个.而没有多个.
    str = str.replace(/\.{2,}/g, '.')
    str = str.replace(/^\./g, '')
    if (iszero) {
        // 必须保证第一个为数字而不是.
        str = str.replace(/^0/g, '')
    }
    // 保证.只出现一次，而不能出现两次以上
    str = str.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
    // 只能输入两个小数
    str = str.replace(/^(\.)*(\d+)\.(\d\d).*$/, '$1$2.$3')
    if (str.indexOf('.') === -1) {
        str = str.slice(0, len)
    } else {
        str = str.slice(0, len + 3)
    }
    return str
}
/**
 * @param {*} str 校验单数组字
 * @param {*} len 长度限制
 * @param {*} ty 只能输入数字
 * @param {*} num 输入的数字大于 num 则显示1
 * @param {*} iszero 为true 不能已0开头
**/
export const clearNoNumLen = (str, len, ty, num, iszero) => {
    // 先把非数字的都替换掉，除了数字和.
    str = str.replace(/[^\d.]/g, '')
    if (ty) { // 只能输入数字
        str = str.replace(/[^\d]/g, '')
    }
    // 剔除多于的0
    str = str.replace(/^(0+)/, '0').replace(/^(0[1-9]+)/, str.slice(1))
    // 保证只有出现一个.而没有多个.
    str = str.replace(/\.{2,}/g, '.')
    // 必须保证第一个为数字而不是.
    str = str.replace(/^\./g, '')
    if (iszero) {
        // 必须保证第一个数字不为0
        str = str.replace(/^0/g, '')
    }
    // 保证.只出现一次，而不能出现两次以上
    str = str.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
    // 只能输入两个小数
    str = str.replace(/^(\.)*(\d+)\.(\d\d).*$/, '$1$2.$3')
    if (str.indexOf('.') === -1) {
        str = str.slice(0, len)
    } else {
        str = str.slice(0, len + 3)
    }
    if (str > num) {
        str = 1
    }
    return str
}
/**
 * 设置动态路由
 * @param {*} router 本地路由
 * @param {*} newRouter 动态获取路由
 * @param {*} accessList 动态获取按钮权限
 * @return {*} menuList 新路由
 */
export const setRouterByRoles = (newRouter, accessList) => {
    let routeMenu = []
    let roles = []
    /** zch-2021-09-07
     * 递归整合权限码
     * @param {*} roles 权限集合
     * @param {*} children 子元素
     * @returns 整合后的权限集合
     */
    const getRouteByTree = (roles, children) => {
        children.map(menu => {
            if (!roles.includes(menu.code)) {
                roles.push(menu.code)
                if (menu.children) {
                    getRouteByTree(roles, menu.children)
                }
            }
        })
        return roles
    }
    newRouter.map(val => {
        if (!roles.includes(val.code)) {
            roles.push(val.code)
        }
        if (val.code.indexOf(config.projectName) > -1 && val.children && val.children.length) {
            routeMenu = val.children
        }
    })

    roles = getRouteByTree(roles, routeMenu)
    for (const key in accessList) {
        if (!roles.includes(key)) {
            roles.push(key)
        }
        accessList[key].map(item => {
            if (!roles.includes(item.code)) {
                roles.push(item.code)
            }
        })
    }
    // console.log(roles, newRouter, accessList)
    return { roles }
}
/** 判断是否为IE9以上，不是则提示下载最新浏览器
 * @return Boolean
 */
export const isLowerIEVersion = () => {
    /* 取得浏览器的userAgent字符串 */
    var userAgent = navigator.userAgent
    /* 判断是否IE<11浏览器 */
    var isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1
    /* 判断是否IE的Edge浏览器 */
    var isEdge = userAgent.indexOf('Edge') > -1 && !isIE
    var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1
    if (isIE) {
        var reIE = new RegExp('MSIE (\\d+\\.\\d+)')
        reIE.test(userAgent)
        var fIEVersion = parseFloat(RegExp['$1'])
        if (fIEVersion === 7) {
            return 7
        } else if (fIEVersion === 8) {
            return 8
        } else if (fIEVersion === 9) {
            return 9
        } else if (fIEVersion === 10) {
            return 10
        } else {
            return 6
        }
    } else if (isEdge) {
        return 'edge'
    } else if (isIE11) {
        return 11
    } else {
        return false
    }
}

/**
  *
  * @param fn {Function}   实际要执行的函数
  * @param delay {Number}  延迟时间，也就是阈值，单位是毫秒（ms）
  *
  * @return {Function}     返回一个“去弹跳”了的函数
  */
export const debounce = (fn, delay) => {
    // 定时器，用来 setTimeout
    var timer

    // 返回一个函数，这个函数会在一个时间区间结束后的 delay 毫秒时执行 fn 函数
    return function () {
        // 保存函数调用时的上下文和参数，传递给 fn
        var context = this
        var args = arguments

        // 每次这个返回的函数被调用，就清除定时器，以保证不执行 fn
        clearTimeout(timer)

        // 当返回的函数被最后一次调用后（也就是用户停止了某个连续的操作），
        // 再过 delay 毫秒就执行 fn
        timer = setTimeout(function () {
            fn.apply(context, args)
        }, delay)
    }
}

/**
 * 2021-08-11 zch
 * 验证重复元素，有重复返回true；否则返回false
 * @params arr: 数组，key: 传入后数组里面是对象需要该字段，验证数组对象里面的字段是否重复
 * @return { Boolean }
 * console.log(isRepeat([{ num: 200, key: '123' }, { num: '200', key: '12312' }], 'num'), '12312312') => true
 * console.log(isRepeat([12, 2, 5]), 'false') => false
 */
export const isRepeat = (arr, key) => {
    let hash = {}
    for (let i in arr) {
        if (key) {
            if (hash[arr[i][key]]) {
                return true
            }
        } else {
            if (hash[arr[i]]) {
                return true
            }
        }
        // 不存在该元素，则赋值为true，可以赋任意值，相应的修改if判断条件即可
        if (key) {
            hash[arr[i][key]] = true
        } else {
            hash[arr[i]] = true
        }
    }
    return false
}
